package utilities;

import engine.Constraint;
import engine.Equation;
import engine.Problem;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class ProblemParser {

    private String stringProblem;
    private final static Charset ENCODING = StandardCharsets.UTF_8;
    private String varName;

    public ProblemParser(String stringProblem, String varName) {
        this.stringProblem = stringProblem;
        this.varName = varName;
    }
    
    /*
     * Retourne le fichier dans une chaine de caractère
     * IOException si le fichier est introuvable
     */
    public static String readFile(File file) throws IOException{
        String buffer = "";
        
        Path path = Paths.get(file.getAbsolutePath());
        List<String> lines = Files.readAllLines(path, ENCODING);
        
        for(String line : lines){
            buffer += line + "\n";
        }
        
        return buffer;
    }

    /*
     * Remplit f et g du problème
     * IOException si le fichier n'existe pas
     * InvalidFormatException si le format du fichier est incorrect
     */
    public Problem problemFromString() throws IOException, InvalidFormatException {

        String[] tabLines = this.stringProblem.split("\n");
        
        /*for(String line : tabLines){
            System.out.println(line);
        }*/
        
        //Il doit y avoir au minimum 3 lignes
        if (tabLines.length < 3) {
            throw new InvalidFormatException("The Problem should containt at least 3 lines");
        }

        //Supression du préfixe "f:" et des espaces
        String lineF = tabLines[0];
        lineF = lineF.replaceAll("f:", "");
        lineF = lineF.replace(" ", "");

        Equation eqF = new Equation(lineF, this.varName);

        //Suppression du préfixe "g:" et des espaces
        String lineG = tabLines[1];
        lineG = lineG.replaceAll("g:", "");
        lineG = lineG.replace(" ", "");

        //Equations de g
        ArrayList<String> equationsGString = new ArrayList<String>();
        for (String eq : lineG.split(";")) {
            equationsGString.add(eq);
        }

        ArrayList<Equation> equationsG = new ArrayList<Equation>();
        for (String eq : equationsGString) {
            equationsG.add(new Equation(eq, this.varName));
        }

        //Bornes
        String lineBornes = tabLines[2];
        lineBornes = lineBornes.replaceAll("bornes:", "");
        lineBornes = lineBornes.replace(" ", "");
        lineBornes = lineBornes.replace("(", "");
        lineBornes = lineBornes.replace(")", "");


        String[] splitBornes = lineBornes.split(",");

        if (splitBornes.length < 2) {
            throw new InvalidFormatException("Minimum bounds should be separated from maximum bounds with a comma.");
        }

        String[] bornesInf = splitBornes[0].split(";");
        String[] bornesSup = splitBornes[1].split(";");

        if (bornesInf.length != bornesSup.length) {
            throw new InvalidFormatException("There should be the same number of minimum bounds than maximum bounds.");
        }

        ArrayList<Double> bornesInfDouble;
        ArrayList<Double> bornesSupDouble;

        try {
            //Conversion en double
            bornesInfDouble = new ArrayList<Double>();
            bornesSupDouble = new ArrayList<Double>();

            for (String str : bornesInf) {
                Double nb = Double.parseDouble(str);
                bornesInfDouble.add(nb);
            }

            for (String str : bornesSup) {
                Double nb = Double.parseDouble(str);
                bornesSupDouble.add(nb);
            }
        } catch (NumberFormatException ex) {
            throw new InvalidFormatException("Bounds are not numeric.");
        }

        Constraint g = new Constraint(bornesInfDouble, bornesSupDouble, equationsG);
        
        Problem prob = new Problem(eqF, g);
        System.out.println(prob);
        
        return prob;
    }
}
